package cn.edu.qzuie.artist.module.td.service.student;

import cn.edu.qzuie.artist.framework.common.enums.UserTypeEnum;
import cn.edu.qzuie.artist.module.system.api.oauth2.OAuth2TokenApi;
import cn.edu.qzuie.artist.module.system.api.oauth2.dto.OAuth2AccessTokenCreateReqDTO;
import cn.edu.qzuie.artist.module.system.api.oauth2.dto.OAuth2AccessTokenRespDTO;
import cn.edu.qzuie.artist.module.system.enums.oauth2.OAuth2ClientConstants;

import cn.edu.qzuie.artist.module.td.controller.app.student.vo.AppStudentAuthLoginRepVo;
import cn.edu.qzuie.artist.module.td.controller.app.student.vo.AppStudentAuthLoginRespVo;

import cn.hutool.core.collection.CollUtil;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import cn.edu.qzuie.artist.module.td.controller.admin.student.vo.*;
import cn.edu.qzuie.artist.module.td.dal.dataobject.student.StudentDO;
import cn.edu.qzuie.artist.framework.common.pojo.PageResult;
import cn.edu.qzuie.artist.framework.common.pojo.PageParam;
import cn.edu.qzuie.artist.framework.common.util.object.BeanUtils;

import cn.edu.qzuie.artist.module.td.dal.mysql.student.StudentMapper;

import javax.annotation.Resource;
import javax.validation.Valid;

import static cn.edu.qzuie.artist.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.edu.qzuie.artist.module.system.enums.ErrorCodeConstants.*;
import static cn.edu.qzuie.artist.module.system.enums.ErrorCodeConstants.STUDENT_NOT_EXISTS;
import static cn.edu.qzuie.artist.module.td.enums.ErrorCodeConstants.*;

/**
 * 学生 Service 实现类
 *
 * @author 泉信管理员
 */
@Service
@Validated
public class StudentServiceImpl implements StudentService {

    @Resource
    private StudentMapper studentMapper;


    @Resource
    private OAuth2TokenApi oauth2TokenApi;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Override
    public AppStudentAuthLoginRepVo login(@Valid AppStudentAuthLoginRespVo reqVO) {
        // 使用学号 + 密码，进行登录。
        StudentDO student = login0(reqVO.getStudentNo(), reqVO.getPassword());

        // 创建 Token 令牌
        return createTokenAfterLoginSuccess(student, reqVO.getStudentNo(), reqVO.getStudentId());
    }

    @Override
    public AppStudentAuthLoginRepVo refreshToken(String refreshToken) {
        OAuth2AccessTokenRespDTO accessTokenDO = oauth2TokenApi.refreshAccessToken(refreshToken,
                OAuth2ClientConstants.CLIENT_ID_DEFAULT);
        AppStudentAuthLoginRepVo repVo = new AppStudentAuthLoginRepVo();
        repVo.setStudentId(accessTokenDO.getUserId());
        repVo.setRefreshToken(accessTokenDO.getRefreshToken());
        repVo.setExpiresTime(accessTokenDO.getExpiresTime());
        repVo.setAccessToken(accessTokenDO.getAccessToken());
        return repVo;
    }


    /**
     * 生成token
     * @param student
     * @return
     */
    private AppStudentAuthLoginRepVo createTokenAfterLoginSuccess(StudentDO student, String studentNo, Long studentId) {
        // 创建 Token 令牌
        OAuth2AccessTokenRespDTO accessTokenRespDTO = oauth2TokenApi.createAccessToken(new OAuth2AccessTokenCreateReqDTO()
                .setUserId(studentId)
                .setUserType(getUserType().getValue())
                .setClientId(OAuth2ClientConstants.CLIENT_ID_DEFAULT));


        // 手动组装构建返回结果
        AppStudentAuthLoginRepVo repVo = new AppStudentAuthLoginRepVo();
        repVo.setStudentId(studentId);
        repVo.setRefreshToken(accessTokenRespDTO.getRefreshToken());
        repVo.setExpiresTime(accessTokenRespDTO.getExpiresTime());
        repVo.setAccessToken(accessTokenRespDTO.getAccessToken());
        return repVo;
    }
    private StudentDO login0(String StudentNo, String password) {
        // 校验账号是否存在
        StudentDO student = studentMapper.selectOne(new cn.edu.qzuie.artist.framework.mybatis.core.query.LambdaQueryWrapperX<StudentDO>()
                .eq(StudentDO::getStudentNo, StudentNo)
                .eq(StudentDO::getPassword, password));
        return student;
    }


    /**
     * 传身份ID
     * @return
     */

    private UserTypeEnum getUserType() {
        return UserTypeEnum.STUDENT;
    }

    @Override
    public Long createStudent(StudentSaveReqVO createReqVO) {
        // 插入
        StudentDO student = BeanUtils.toBean(createReqVO, StudentDO.class);
        studentMapper.insert(student);
        // 返回
        return student.getId();
    }

    @Override
    public void updateStudent(StudentSaveReqVO updateReqVO) {
        // 校验存在
        validateStudentExists(updateReqVO.getId());
        // 更新
        StudentDO updateObj = BeanUtils.toBean(updateReqVO, StudentDO.class);
        studentMapper.updateById(updateObj);
    }

    @Override
    public void deleteStudent(Long id) {
        // 校验存在
        validateStudentExists(id);
        // 删除
        studentMapper.deleteById(id);
    }

    private void validateStudentExists(Long id) {
        if (studentMapper.selectById(id) == null) {
            throw exception(STUDENT_NOT_EXISTS);
        }
    }

    @Override
    public StudentDO getStudent(Long id) {
        return studentMapper.selectById(id);
    }

    @Override
    public PageResult<StudentDO> getStudentPage(StudentPageReqVO pageReqVO) {
        return studentMapper.selectPage(pageReqVO);
    }

    @Override
    public StudentExcelRespVo batchInsertStudent(List<StudentExcelDataInputVO> importStudents, boolean isupdateSupport) {
        //1.1 参数校验（判断导入的数据是否为空）
        if(CollUtil.isEmpty(importStudents)){
            throw exception(STUDENT_IMPORT_LIST_IS_EMPTY);
        }

        StudentExcelRespVo respVo = StudentExcelRespVo.builder()
                .createUsernames(new ArrayList<>())
                .updateUsernames(new ArrayList<>())
                .failureUsernames(new HashMap<>())
                .build();

        //1.2 参数校验（判断学生姓名是否填写完整）
        for (StudentExcelDataInputVO importStudent : importStudents) {
            System.out.println("sdsdsdsdsdsd"+importStudents);
            String realName = importStudent.getRealName();
            System.out.println("sdsdsdsdsdsd+"+realName);
            if (realName == null || realName.isEmpty()) {
                throw exception(STUDENT_NOT_EXISTS);
            }

            //1.3 参数校验（判断学生已存在）
            StudentDO existStudent = studentMapper.selectByStudentNo(importStudent.getStudentNo());
            if (existStudent == null) {
                // 若不存在，则插入新学生
                studentMapper.insert(BeanUtils.toBean(importStudent,StudentDO.class).setPassword(encodePassword(importStudent.getPassword())));
                respVo.getCreateUsernames().add(importStudent.getRealName());
            }else {
                throw exception(TEACHER_USERNAME_EXISTS);
            }
        }
        return respVo;
    }

    /**
     * 对密码进行加密
     *
     * @param password 密码
     * @return 加密后的密码
     */
    private String encodePassword(String password) {
        return passwordEncoder.encode(password);
    }

}